﻿using System;
using System.Collections.Generic;
using System.Text;

namespace ICSharpCode.WinFormsUI.Core
{
    public class HtmlTextParse
    {
        public static string Parse(string input, out StringCollection result)
        {
            return new HtmlTextParse().DoHtmlTextParse(input, out result);
        }

        private string DoHtmlTextParse(string input, out StringCollection result)
        {
            string text = input;
            string express = @"<font[\s]*(.*?)>(.*?)</font>"; //@"<a[\s]*(.*?)>(.*?)</a>"; //@"<font[\s]*(.*?)>(.*?)</font>"; //@"<font[\s+]*(color|style|bold)='(.*)'>(.*?)</font>";//\<font [color='\w.*']\>(.*?)\</\>
            Regex(express, input, out result);
            return text;
        }

        internal bool Regex(string express, string input, out StringCollection result)
        {
            result = new StringCollection();          
            bool success = false;
            System.Text.RegularExpressions.Regex reg =
                new System.Text.RegularExpressions.Regex(express, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            var match = reg.Match(input);

            int startIndex = 0;

            while (match.Success)
            {
                success = true;               
                StringItem item = new StringItem();
                item.Html = Replace(match.Groups[0].Value);
                item.Context = Replace(match.Groups[1].Value);
                item.Text = Replace(match.Groups[2].Value);
                item.StringIndex = input.IndexOf(match.Groups[0].Value, startIndex);
                item.StringLength = match.Groups[0].Value.Length;
                startIndex += item.StringLength;

                var value = match.Value;
                var attrs = item.Attrs;

                result.Add(item);
                match = match.NextMatch();
            }

            result.Text = input;

            return success;
        }

        internal string Replace(string input)
        {
            return System.Text.RegularExpressions.Regex.Replace(input, "\\s{2,}", " ", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
        }

        internal string Replace(string express, string input)
        {
            string output = string.Empty;
            if (!string.IsNullOrEmpty(input))
            {
                System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(express, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                System.Text.RegularExpressions.Match match = reg.Match(input);
                if (match.Success)
                {
                    var gc = match.Groups;
                    foreach (System.Text.RegularExpressions.Group g in gc)
                    {
                        output = Replace(g.Value + "").Replace(" ", "\\s");
                    }
                    return System.Text.RegularExpressions.Regex.Replace(input, express, output, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                }
            } 
            return input;
        }

        public class StringItem
        {
            public string Text { get; set; }
            public string Html { get; set; }
            public int StringIndex { get; set; }
            public int StringLength { get; set; }
            internal string Context { get; set; }
            public Dictionary<string, string> Attrs
            {
                get
                {
                    Dictionary<string, string> values = null;
                    string _contextString = new HtmlTextParse().Replace("title='.*?'", Context);
                    _contextString = new HtmlTextParse().Replace("onclick='.*?'", _contextString);
                    if (!string.IsNullOrEmpty(_contextString) && _contextString.IndexOf("=") != -1)
                    {
                        values = new Dictionary<string, string>();
                        string[] attrs_array = _contextString.Split(' ');
                        foreach (string attr in attrs_array)
                        {
                            if (attr.IndexOf('=') >= 0)
                            {
                                string key = attr.Split('=')[0].Trim(); //attr.Substring(0, attr.IndexOf('='));  
                                string value = attr.Split('=')[1].Trim('\''); //attr.Substring(attr.IndexOf('=') + 1);  
                                values.Add(key, value);
                            }
                        }
                    }
                    return values;
                }
            }

            public StringItem()
            {

            }

            public StringItem(string text)
                : this()
            {
                this.Text = text;
            }

            public StringItem New(string text)
            {
                return new StringItem(text);
            }

            public StringItem Clone()
            {
                StringItem item = new StringItem();
                item.Text = this.Text;
                item.Html = this.Html;
                item.Context = this.Context;
                item.StringIndex = this.StringIndex;
                item.StringLength = this.StringLength;
                return item;
            }

        }

        public class StringItemEnumerator : System.Collections.IEnumerator
        {
            private int position = -1;
            private StringItem[] _list = null;
            public StringItemEnumerator(List<StringItem> list)
            {
                _list = list.ToArray();
            }

            public bool MoveNext()
            {
                position++;
                return position < _list.Length;
            }

            public void Reset()
            {
                position = -1;
            }

            public object Current
            {
                get
                {
                    return _list[position];
                }
            }

        }

        public class StringCollection : System.Collections.IEnumerable
        {
            private List<StringItem> list = null;
            public string Text { get; set; }

            public int Count
            {
                get
                {
                    return list == null ? 0 : list.Count;
                }
            }

            public StringCollection()
            {
                list = new List<StringItem>();
            }

            public System.Collections.IEnumerator GetEnumerator()
            {
                return new StringItemEnumerator(list);
            }
          
            public void Add(StringItem item)
            {
                this.list.Add(item);
            }

            public void Clear()
            {
                this.list.Clear();
            }

            public void Exception(string text)
            {
                list = new List<StringItem>();
                Text = text;
            }

        }

    }
}
